/**
 * Copyright (C), 2015-2019, 山东桔灯行信息科技有限公司
 * FileName: VerifyCardService
 * Author:   chen
 * Date:     19-5-27 上午9:16
 * Description: 校验卡号服务
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.duochuang.verifycard.application;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.duochuang.verifycard.domain.*;
import com.duochuang.verifycard.exception.InterfaceException;
import com.duochuang.verifycard.util.*;
import com.duochuang.verifycard.web.CardVerifyDTO;
import com.duochuang.verifycard.web.VerifyResultDTO;
import com.google.common.primitives.Booleans;
import com.querydsl.core.types.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.transaction.Transactional;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.duochuang.verifycard.util.ConstantUtil.USER_ID;

/**
 * 〈一句话功能简述〉<br> 
 * 〈校验卡号服务〉
 *
 * @author chen
 * @create 19-5-27
 * @since 1.0.0
 */
@Service
@Slf4j
public class VerifyCardService {
    @Autowired
    private SystemCodeRepository systemCodeRepository;
    @Autowired
    private LockOrderRepository lockOrderRepository;
    @Autowired
    private RestTemplate restTemplate;

    public void verifyCard(CardVerifyDTO cardVerifyDTO) throws InterfaceException {

        //验证签名
        HashMap<String,String> map=new HashMap<>();
        // (userOrderNumber+ cardNo+ timeStr)
        map.put("userOrderNumber",cardVerifyDTO.getUserOrderNumber());
        map.put("cardNo",cardVerifyDTO.getCardNo());
        map.put("operatorCode",cardVerifyDTO.getOperatorCode());
        map.put("timeStr",cardVerifyDTO.getTimeStr());
        map.put("privateKey", cardVerifyDTO.getPrivateKey());

        if( !SignUtil.verifySign(map, cardVerifyDTO.getSign())){
            throw new InterfaceException(23,"签名认证不通过");
        }
        new Thread(){
            public void run(){
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    log.error("异常", e);
                }
                callback(cardVerifyDTO);
            }
        }.start();
    }

    //回调
    private void callback(CardVerifyDTO cardVerifyDTO){

        SystemCode systemCode= new SystemCode();
        Optional<SystemCode> optional;
        String result = "1";
        //中石化001 中石油 002
        switch (cardVerifyDTO.getOperatorCode()){
            case "001":
                optional = systemCodeRepository.findById(ConstantUtil.SINOPEC_CODE);
                if (optional.isPresent()){
                    systemCode = optional.get();
                }
                String cardNo = cardVerifyDTO.getCardNo();
                String cookie = systemCode.getValue();
                Integer code = SinopecVerifyCardUtil.verifyCard(cardNo, cookie).getStatus();
                if (code.equals(0)){ // 成功-返回失败
                    result = "1";
                } else {
                    result = "2"; // 失败-返回不确定;
                }
                break;
            case "002":
                optional = systemCodeRepository.findById(ConstantUtil.PETRO_CHINA_CODE);
                if (optional.isPresent()){
                    systemCode = optional.get();
                }
                cardNo = cardVerifyDTO.getCardNo();
                cookie = systemCode.getValue();
                String res = PetroChinaVerifyCardUtil.verifyCard(cardNo, cookie);
                try {
                    result = JSONObject.parseObject(res).getString("status");
                } catch (JSONException e){}
                break;
        }

        // 签名
        Map<String,String> param = new HashMap<>();
        param.put("userOrderNumber",cardVerifyDTO.getUserOrderNumber());
        param.put("cardNo",cardVerifyDTO.getCardNo());
        param.put("operatorCode",cardVerifyDTO.getOperatorCode());
        String timeStr=String.valueOf(System.currentTimeMillis());

        String sign = null;
        try {
            sign=SignUtil.mySign(param, timeStr).get("sign");
        } catch (Exception e) {
            e.printStackTrace();
        }
        String url= cardVerifyDTO.getUserPlatUrl();
        if (StringUtils.isNotEmpty(url)){
            String callbackUrl = cardVerifyDTO.getUserPlatUrl() + "?userOrderNumber={userOrderNumber}&cardNo={cardNo}" +
                    "&operatorCode={operatorCode}&timeStr={timeStr}&sign={sign}";
            String s = restTemplate.getForObject(callbackUrl, String.class, cardVerifyDTO.getUserOrderNumber(),
                    cardVerifyDTO.getCardNo(), cardVerifyDTO.getOperatorCode(), timeStr, sign);
            log.info("验证的回调请求返回结果：{}", s);
        } else {
            log.warn("用户回调的url为空");
        }

    }
    //订单回调
    public boolean orderCallback(VerifyResultDTO verifyResult){
        String url = "http://60.205.171.129:8160/plugin/callbackOrder.do";
//                "userId={userId}&orderId={orderId}&status={status}&errorCode={errorCode}&errorMsg={errorMsg}&sign={sign}";
        Map<String,String> param = new HashMap<>();
        /**
         * userId
         * orderId
         * status
         * errorCode
         * errorMsg
         * sign
         */
        param.put("userId", USER_ID);
        param.put("orderId", verifyResult.getOrderId());
        param.put("status", verifyResult.getStatus());
        param.put("errorCode", verifyResult.getErrorCode());
        param.put("errorMsg", verifyResult.getErrorMsg());
        String sign= SignUtil.sign(param).get("sign");
        log.info("订单回调签名：{}", sign);
        param.put("sign", sign);
        log.info(url, param);
        try {
            MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
            postParameters.setAll(param);
            HttpHeaders requestHeaders = new HttpHeaders();
            requestHeaders.add("Accept", "application/json;charset=UTF-8");
            requestHeaders.add("Content-Type", "application/x-www-form-urlencoded");
            String result = restTemplate.postForEntity(url, new HttpEntity(postParameters, requestHeaders), String.class).getBody();
            log.info("{}: 订单回调的结果:{}", verifyResult.getOrderId(), result);
            return result.contains("success");
        } catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

//    @Scheduled(fixedRate=5000)
    public void task(){

    }
    public void work(){
        SystemCode systemCode = new SystemCode();
        Optional<SystemCode> optional;
        String result = "0";
        Boolean doWhile = true;

        do {
            optional = systemCodeRepository.findById(ConstantUtil.SINOPEC_CODE);
            if (optional.isPresent()){
                systemCode = optional.get();
                if (BooleanUtils.isNotTrue(systemCode.getStatus())){
                    doWhile = false;
                    return;
                }
            }
            //
            LockOrder lockOrder = getOrderLock();
            if (lockOrder!=null){
                String cardNo = lockOrder.getUid();
                String orderid = lockOrder.getOrderId();
                String cookie = systemCode.getValue();
                String errorCode = "";
                String errorMsg = "";
                VerifyCode verifyCode= SinopecVerifyCardUtil.verifyCard(cardNo, cookie);
                Integer code = verifyCode.getStatus();
                if (code.equals(0)) { // 0成功-返回失败0
                    result = "0";
                } else if (code.equals(2)){ // cookie 过期
                    systemCode.setStatus(false);
                    systemCodeRepository.save(systemCode);
                    doWhile = false;
                    result = "0";
//                    return;
                } else {
                    result = "2"; // -1失败-返回不确定2;
                    errorCode = String.valueOf(code);
                    errorMsg = verifyCode.getMsg();
                }
                VerifyResultDTO verifyResultDTO = new VerifyResultDTO(USER_ID, orderid, result, errorCode, errorMsg);
                Boolean falg = orderCallback(verifyResultDTO);
                if (falg){
                    lockOrder.setCallbackStatus(true);
                    lockOrder.setCallbackData(JSONObject.toJSONString(verifyResultDTO));
                    lockOrderRepository.save(lockOrder);
                }
            }
        }while (doWhile);

    }

    /**
     * 锁定订单-同时获取订单信息
     * @return
     */
    public LockOrder getOrderLock(){
        String url = "http://60.205.171.129:8160/plugin/lockOrder.do?" +
                "userId={userId}&ts={timeStr}&sign={sign}";
        String userId = USER_ID;
        String timeStr = String.valueOf(System.currentTimeMillis());
        // 签名
        Map<String,String> param = new HashMap<>();
        param.put("userId", "552");
        param.put("ts", timeStr);

        String sign = null;
        try {
            sign=SignUtil.sign(param).get("sign");
        } catch (Exception e) {
            e.printStackTrace();
        }
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("Accept", "application/json;charset=UTF-8");
        try {
            LockOrder lockOrder = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity(requestHeaders), LockOrder.class, userId, timeStr, sign).getBody();
            log.info("锁定订单返回结果为：{}", JSONObject.toJSON(lockOrder));
            if (lockOrder.getStatus().equals("success") && StringUtils.isNotEmpty(lockOrder.getOrderId())){
                lockOrder = lockOrderRepository.save(lockOrder);
                return lockOrder;
            }
//            LockOrder finalLockOrder = lockOrder;
//            new Thread(() -> orderCallback(finalLockOrder)).start();
        } catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public Page<LockOrder> findAll(String orderId, String uId, Boolean callbackStatus,Pageable pageable) {
        QLockOrder qLockOrder = QLockOrder.lockOrder;
        Predicate predicate = qLockOrder.orderId.isNotNull();
        if (StringUtils.isNotEmpty(orderId)){
            predicate = qLockOrder.orderId.eq(orderId).and(predicate);
        }
        if (StringUtils.isNotEmpty(uId)){
            predicate = qLockOrder.uid.eq(uId).and(predicate);
        }
        if (Objects.nonNull(callbackStatus)){
            predicate = qLockOrder.callbackStatus.eq(callbackStatus).and(predicate);
        }
        return lockOrderRepository.findAll(predicate, pageable);
    }

    @Transactional
    public void orderCallbackById(LockOrder lockOrder) {
        VerifyResultDTO verifyResultDTO = JSONObject.parseObject(lockOrder.getCallbackData(), VerifyResultDTO.class);
        lockOrder.setCallbackStatus(true);
        lockOrderRepository.save(lockOrder);
        orderCallback(verifyResultDTO);
    }
}
